﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

/// <summary>
/// UI管理器层
/// </summary>
[DefaultExecutionOrder(-100)]
public class UIManager : MonoBehaviour
{
    public Transform trsRoot;
    public UILayerCollect[] layerList;
    public static UIManager Instance;

    [HideInInspector] public GameObject mBlocker = null;


    private void Awake()
    {
        Instance = this;

        if (mBlocker == null)
        {
            mBlocker = CreateBlocker();
        }

        LockUserTouch(false);

    }

    public void LockUserTouch(float time = .2f)
    {
        if (mBlocker)
        {
            mBlocker.transform.SetAsLastSibling();
            mBlocker.SetActive(true);
            Invoke("UnlockUserTouch", time);
        }
    }

    private void UnlockUserTouch()
    {
        if (mBlocker)
        {
            mBlocker.SetActive(false);
        }
    }

    public void LockUserTouch(bool _lock)
    {
        if (mBlocker)
        {
            mBlocker.transform.SetAsLastSibling();
            mBlocker.SetActive(_lock);
        }
    }


    public (GameObject, Transform) GetFromPrefab<T>()
    {
        for (int i = 0; i < layerList.Length; i++)
        {
            if (!layerList[i].gameObject.activeSelf) continue;
            var prefab = layerList[i].GetFromPrefab<T>();
            if (prefab != null) {
                Transform curRoot = layerList[i].trsRoot;
                if (curRoot != null) {
                    return (prefab, curRoot);    
                } else {
                    return (prefab, trsRoot);    
                }
            }
        }
        return (null, null);
    }

    /// <summary>
    /// 获取一个弹窗界面，如果UIManager 下找不到，那从 prefabList里查找，然后捞出来
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T GetWindow<T>(bool autoActive = true) where T : Component
    {
        T selectComp = default(T);
        //反射激活类

        string compName = typeof(T).Name;

        for (int i = 0; i < layerList.Length; i++)
        {
            var curLayer = layerList[i];
            if (!curLayer.gameObject.activeSelf) continue;
             //从缓存中读取弹窗界面
            for (int j = 0; j < curLayer.transform.childCount; j++)
            {
                var trans = curLayer.transform.GetChild(j);
                T comp = trans.GetComponent<T>();
                if (comp != null)
                {
                    GameObject obj = comp.gameObject;
                    //从缓存中激活使用
                    if (obj != null)
                    {
                        if(curLayer.trsRoot == null) {
                            obj.transform.SetParent(trsRoot);
                        } else {
                            obj.transform.SetParent(curLayer.trsRoot);
                        }
                        
                        obj.SetActive(autoActive);
                        selectComp = comp;
                        break;
                    }
                }
            }
        }

       
        //重新创建一个新的界面
        if (selectComp == null)
        {
            // print(compName + "IS NULL");
            var result = this.GetFromPrefab<T>();
            if (result.Item1 != null)
            {
                var myGameObject = Instantiate(result.Item1);
                myGameObject.transform.SetParent(result.Item2);
                myGameObject.transform.localScale = Vector3.one;
                myGameObject.transform.localEulerAngles = Vector3.zero;
                myGameObject.transform.localPosition = Vector3.zero;
                var rect = myGameObject.GetComponent<RectTransform>();
                if (rect)
                {
                    rect.offsetMin = new Vector2(0, 0);
                    rect.offsetMax = new Vector2(0, 0);
                }

                myGameObject.SetActive(autoActive);
                selectComp = myGameObject.GetComponent<T>();//获取T
            }
        }
        selectComp.transform.SetAsLastSibling();

        return selectComp;

    }

    
    
    public GameObject GetWindowByName (string name) {
        foreach (var curLayer in layerList)
        {
             //从缓存中读取弹窗界面
            foreach (Transform trans in curLayer.transform)
            {
                if (trans.name == name) {
                    return trans.gameObject;
                }
            }
        }
        return null;
    }

    public bool IsWindowOpen<T>() where T : Component
    {
        GameObject go = null;
        foreach (var curLayer in layerList)
        {
            if (!curLayer.gameObject.activeSelf) continue;
            go = curLayer.GetTargetGameObject<T>();
            if (go != null) break;
        }
        if (go == null) return false;
        return go.activeSelf;
    }


    public T GetWindowComponent<T>()where T : Component
    {
        string compName = typeof(T).Name;

        for (int i = 0; i < layerList.Length; i++)
        {
            var curLayer = layerList[i];
            //从缓存中读取弹窗界面
            for (int j = 0; j < curLayer.transform.childCount; j++)
            {
                var trans = curLayer.transform.GetChild(j);
                T comp = trans.GetComponent<T>();
                if (comp != null)
                {
                    return comp;
                }
            }
        }
        return null;
    }

    public bool IsShowLayerUI(string layerName)
    {
        
        for (int i = 0; i < layerList.Length; i++)
        {
            var curLayer = layerList[i];
            if (!curLayer.gameObject.activeSelf) continue;

            if (layerName == curLayer.gameObject.name)
            {
                //从缓存中读取弹窗界面
                for (int j = 0; j < curLayer.transform.childCount; j++)
                {
                    Transform trans = curLayer.transform.GetChild(j);
       
                    if (trans.gameObject.activeSelf)
                    {
                        return true;
                    }
                }
            }
        }

        return false;
    }


    /// <summary>
    /// 打开一个弹窗
    /// </summary>
    /// <param name="openToTop"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T OpenWindow<T>() where T : Component
    {
        return this.GetWindow<T>(true);
    }

    /// <summary>
    /// 创建屏蔽用的对象，屏蔽层级低于30000
    /// </summary>
    /// <returns></returns>
    public GameObject CreateBlocker(int sortingOrder = 29999)
    {
        var node = new GameObject();
        node.name = "[Blocker]";
        var parentCanvas = this.transform.GetComponentInParent<Canvas>();
        node.transform.SetParent(parentCanvas.transform);

        var canvas = node.AddComponent<Canvas>();
        canvas.overrideSorting = true;
        canvas.sortingOrder = 29999;

        var graphic = node.AddComponent<GraphicRaycaster>();
        graphic.ignoreReversedGraphics = true;
        var image = node.AddComponent<Image>();
        image.color = new Color(1, 1, 1, 0);

        var rect = node.GetComponent<RectTransform>();
        rect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, 0);
        rect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 0);
        rect.anchorMin = Vector2.zero;
        rect.anchorMax = Vector2.one;

        var button = node.AddComponent<Button>();
        return node;
    }



    /// <summary>
    /// 添加节点下的所有按钮点击回调事件
    /// </summary>
    /// <param name="trsRoot"></param>
    public void AddBtnListener (Transform trsRoot) {
        Button[] btnArr = trsRoot.GetComponentsInChildren<Button>(true);
        for (int i = 0; i < btnArr.Length; i++)
        {
            Transform child = btnArr[i].transform;
            btnArr[i].onClick.AddListener(() => {
#if UNITY_TEST
                UnityEngine.Debug.Log("AddBtnListener  target.name = " + child.name);
#endif
                trsRoot.SendMessage("OnBtnClick",child); 
            });
        }
    }
    // public void AddBtnListener (Transform curRoot) {
    //     DelayAddBtnListener(curRoot).Forget();
    // }
    // private async UniTaskVoid DelayAddBtnListener (Transform curRoot) {
    //     await UniTask.Delay(TimeSpan.FromSeconds(0.1f));
    //     Button[] btnArr = curRoot.GetComponentsInChildren<Button>(true);
    //     for (int i = 0; i < btnArr.Length; i++)
    //     {
    //         AddBtnListener(curRoot, btnArr[i]).Forget();
    //     }
    // }
    // private async UniTaskVoid AddBtnListener (Transform trsRoot, Button btn) {
    //     IUniTaskAsyncEnumerator<AsyncUnit> asyncEnumerator = btn.OnClickAsAsyncEnumerable().GetAsyncEnumerator();
    //     while (true)
    //     {
    //         await asyncEnumerator.MoveNextAsync();
    //         trsRoot.SendMessage("OnBtnClick", btn);
    //         await UniTask.Delay(TimeSpan.FromSeconds(0.1f));
    //     }
    // }

    /// <summary>
    /// 添加节点下的所有Toggle点击回调事件
    /// </summary>
    /// <param name="trsRoot"></param>
    public void AddToggleListener (Transform trsRoot) {

        Toggle[] tgArr = trsRoot.GetComponentsInChildren<Toggle>(true);
        for (int i = 0; i < tgArr.Length; i++)
        {
            Transform child = tgArr[i].transform;
            AddTgOnValueChangedListener(trsRoot, tgArr[i]);
        }
    }
    private void AddTgOnValueChangedListener (Transform trsRoot, Toggle tg) {
        tg.onValueChanged.AddListener((bool isOn) => {
            trsRoot.SendMessage("OnToggle", tg);
        });

    }
    
    /// <summary>
    /// 是否可点击
    /// </summary>
    /// <returns></returns>
    public bool IsTouchedUI()
    {
        bool touchedUI = false;
        //TODO 移动端
        if (Application.isMobilePlatform)  
        {
            if (Input.touchCount > 0 && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
            {
                touchedUI = true;
            }
        }
        //TODO PC端
        else if (EventSystem.current.IsPointerOverGameObject())
        {
            touchedUI = true;
        }
        return touchedUI;
    }


       //延迟信息记录
    public IDictionary<string, float> clickDelay = new Dictionary<string, float>();
    private IList<string> allClickKeys = new List<string>(); 
    /// <summary>
    /// 当前按钮是否处于冷却时间
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool IsClickDelay (string key) {
        bool isDelay = false;
        if (clickDelay.ContainsKey(key) && clickDelay[key] > 0f) {
            isDelay = true;
        }
        return isDelay;
    }
    /// <summary>
    /// 添加按钮点击的冷却时间
    /// </summary>
    /// <param name="key"></param>
    /// <param name="dt"></param>
    public void ResetClickDelay (string key, float dt) {
        if (clickDelay.ContainsKey(key)) {
            clickDelay[key] = dt;
        } else {
            allClickKeys.Add(key);
            clickDelay.Add(key, dt);
        }
    }
    /// <summary>
    /// 刷新按钮的冷却时间
    /// </summary>
    public void RefreshClickDelay () {
        for (int i = 0; i < allClickKeys.Count; i++)
        {
            if (clickDelay[allClickKeys[i]] > 0) {
                clickDelay[allClickKeys[i]] -= Time.deltaTime;
            }
        }
    }

}

